package simulaco.business;

import gminet.infra.business.BusinessException;
import gminet.infra.business.BusinessObject;
import gminet.infra.db.Transaction;
import gminet.infra.db.TransactionException;
import gminet.infra.toolkit.DateToolkit;
import gminet.infra.toolkit.NumberToolkit;
import gminet.infra.toolkit.StringToolkit;

import java.sql.Connection;
import java.util.Date;
import java.util.List;

import simulaco.dao.SimuladoModeloDAO;
import simulaco.dao.SimuladoModeloFilter;
import simulaco.dto.SimuladoModelo;
import simulaco.dto.SimuladoModeloMateria;
import simulaco.dto.Situacao;

public class SimuladoModeloBusiness extends BusinessObject {

    public static SimuladoModelo findByPK(int codigoSimulado) throws TransactionException {

        SimuladoModelo simuladoModelo = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            simuladoModelo = SimuladoModeloDAO.findByPK(codigoSimulado, conn);
            if (simuladoModelo != null) {
                List<SimuladoModeloMateria> listaSimuladoMaterias;
                listaSimuladoMaterias = SimuladoModeloMateriaBusiness.findBySimuladoModelo(codigoSimulado, conn);
                simuladoModelo.setListaSimuladoMaterias(listaSimuladoMaterias);
            }
        } finally {
            transaction.release();
        }
        return simuladoModelo;
    }

    public static List<SimuladoModelo> findAll() throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            simuladoModelos = SimuladoModeloDAO.findAll(conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return simuladoModelos;
    }

    public static List<SimuladoModelo> findActives() throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            SimuladoModeloFilter simuladoModeloFilter = new SimuladoModeloFilter();
            simuladoModeloFilter.setCodigoSituacao(Situacao.HABILITADO.getCodigo());
            simuladoModelos = SimuladoModeloDAO.findByFilter(simuladoModeloFilter, conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return simuladoModelos;
    }

    public static List<SimuladoModelo> findByInstituicao(int instituicaoId) throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            simuladoModelos = findByInstituicao(instituicaoId, conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return simuladoModelos;
    }

    protected static List<SimuladoModelo> findByInstituicao(int instituicaoId, Connection conn)
            throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        SimuladoModeloFilter simuladoModeloFilter = new SimuladoModeloFilter();
        simuladoModeloFilter.setCodigoInstituicao(instituicaoId);
        simuladoModelos = SimuladoModeloDAO.findByFilter(simuladoModeloFilter, conn);
        return simuladoModelos;
    }

    public static List<SimuladoModelo> findByOrgao(int orgaoId) throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            simuladoModelos = findByInstituicao(orgaoId, conn);
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return simuladoModelos;
    }

    protected static List<SimuladoModelo> findByOrgao(int orgaoId, Connection conn) throws TransactionException {

        List<SimuladoModelo> simuladoModelos = null;
        SimuladoModeloFilter simuladoModeloFilter = new SimuladoModeloFilter();
        simuladoModeloFilter.setCodigoOrgao(orgaoId);
        simuladoModelos = SimuladoModeloDAO.findByFilter(simuladoModeloFilter, conn);
        return simuladoModelos;
    }

    public static SimuladoModelo insert(SimuladoModelo simuladoModelo) throws BusinessException, TransactionException {

        SimuladoModelo newSimuladoModelo = null;
        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // VALIDANDO DADOS
            if (simuladoModelo.getNivel().getCodigo() == 0 && simuladoModelo.getOrgao().getCodigo() == 0
                    && simuladoModelo.getInstituicao().getCodigo() == 0) {
                throw new BusinessException(
                        "Dados inválidos. Pelo menos um dos seguintes campos devem ser preenchidos: Nível, Órgão e Instituição.");
            }
            // SIMULADO MODELO
            Date dataAtual = DateToolkit.getDate();
            int rangeId = createRangeId(simuladoModelo.getIdentificacao());
            simuladoModelo.setCodigo(SimuladoModeloDAO.getNextCodigo(conn, rangeId, rangeId + 1000));
            if (simuladoModelo.getSituacao().getCodigo() == 0) {
                simuladoModelo.setSituacao(Situacao.DESABILITADO);
            }
            simuladoModelo.setDataCadastro(dataAtual);
            SimuladoModeloDAO.insert(simuladoModelo, conn);
            // CONCURSO MATERIAS
            SimuladoModeloMateriaBusiness.insertFromSimuladoModelo(simuladoModelo, conn);
            // COMMIT
            transaction.commit();
            //
            newSimuladoModelo = simuladoModelo;
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
        return newSimuladoModelo;
    }

    private static int createRangeId(String simuladoModeloName) {

        String strCodigo = "1";
        String caracter1 = simuladoModeloName.substring(0, 1).toUpperCase();
        String caracter2 = simuladoModeloName.length() > 1 ? simuladoModeloName.substring(1, 2).toUpperCase() : "A";
        int valor1 = Math.abs(caracter1.compareTo("A") + 1);
        if (StringToolkit.isDigit(caracter1)) {
            valor1 = 0;
        }
        int valor2 = Math.abs(caracter2.compareTo("A") / 3);
        if (StringToolkit.isDigit(caracter2)) {
            valor2 = 0;
        }
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor1, 99), 2);
        strCodigo += NumberToolkit.getStringFromInt(Math.min(valor2, 9), 1);
        strCodigo += "000";
        return Integer.parseInt(strCodigo);
    }

    public static void update(SimuladoModelo simuladoModelo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // VALIDANDO DADOS
            if (simuladoModelo.getNivel().getCodigo() == 0 && simuladoModelo.getOrgao().getCodigo() == 0
                    && simuladoModelo.getInstituicao().getCodigo() == 0) {
                throw new BusinessException(
                        "Dados inválidos. Pelo menos um dos seguintes campos devem ser preenchidos: Nível, Órgão e Instituição.");
            }
            // SIMULADO MODELO
            SimuladoModeloDAO.update(simuladoModelo, conn);
            // CONCURSO MATERIAS
            SimuladoModeloMateriaBusiness.updateFromSimulado(simuladoModelo, conn);
            // COMMIT
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void updateStatus(SimuladoModelo simuladoModelo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            SimuladoModelo auxSimuladoModelo = SimuladoModeloDAO.findByPK(simuladoModelo.getCodigo(), conn);
            auxSimuladoModelo.setSituacao(simuladoModelo.getSituacao());
            SimuladoModeloDAO.update(auxSimuladoModelo, conn);
            // COMMIT
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

    public static void delete(SimuladoModelo simuladoModelo) throws BusinessException, TransactionException {

        Transaction transaction = createTransaction();
        try {
            Connection conn = transaction.getConnection();
            // EXCLUI QUESTOES SIMULADO
            SimuladoModeloMateriaBusiness.deleteBySimulado(simuladoModelo, conn);
            // EXCLUI O SIMULADO
            SimuladoModeloDAO.delete(simuladoModelo, conn);
            //
            transaction.commit();
        } catch (TransactionException te) {
            transaction.rollback();
            throw te;
        } finally {
            transaction.release();
        }
    }

}
